/**
 * 封装 axios 的请求和返回
 */
import axios from 'axios'
// 使用element-ui Message做消息提醒
import { Message } from 'element-ui';
import qs from 'qs'
import router from "@/router";
import setting from '@/config/setting'
// import vuex from '../vuex'

// 1、--- 创建新的 axios 实例
const service = axios.create({
  // 请求后台地址， baseURL + 你写的请求地址
  // baseURL: "http://127.0.0.1:8084/ps/",
  baseURL: setting.baseURL,
  // 超时时间 单位是ms
  timeout: setting.timeout
})

// 定义一个对象用于存储 loginErr 状态，是否出现错误的状态
let loginErr = false;
// 用于跟踪当前正在进行的请求数量
let activeRequests = 0;

// 2、--- 请求拦截器。发请求前做的一些处理，数据转化，配置请求头，设置token,设置loading等，根据需求去添加
service.interceptors.request.use(config => {
  // 请求发起前增加正在进行的请求数量
  activeRequests ++;

  // blob 类型请求不做任何 content-type、参数序列化处理。
  // blob 请求（比如下载图片）是不允许被 stringify 和改 Content-Type 的，否则请求就会变成错误的请求格式，导致后端识别不到参数，甚至请求直接失败 还没有机会到 response 阶段
  if (config.responseType === 'blob') {
    let token = window.localStorage.token;
    config.headers = {};
    if (token) config.headers.token = token;
    return config;
  }

  // 2.1 设置请求头
  if (config.existingFile){
    // 用于上传文件 上传 FormData 文件（multipart/form-data）
    config.headers = {
      'Content-Type':'multipart/form-data'
    }
  } else {
    config.headers = {
      'Content-Type':'application/x-www-form-urlencoded'
    }
  }

  // 2.2 处理数据,文件提交的则不需要序列化
  if (config.existingFile){

  } else {
    //数据转化,也可以使用qs转换
    //sys.data = JSON.stringify(sys.data);
    config.data = qs.stringify(config.data, {
      // true 启用点号语法，这样参数就是 dependList[0].necessary，否则是 dependList[0][necessary]
      allowDots: true,
      arrayFormat: 'indices'
    })
  }

  // 2.3 读取token
  //注意使用token的时候需要引入cookie方法或者用本地localStorage等方法，推荐js-cookie
  let localStorage = window.localStorage;
  // 读取 token
  let token = localStorage.token;
  if (token){
    // 参数中携带token
    //sys.params = {'token':token}
    // 请求头中携带token
    config.headers.token = token;
  }

  return config;
}, error => {
  Promise.reject(error);
})




// 3、--- 响应拦截器
service.interceptors.response.use(response => {
  // 请求完成后减少正在进行的请求数量
  activeRequests --;

  // blob 响应直接返回，不走后续 JSON 业务判断。blob 文件返回根本没有 code 字段，它是二进制流。如果不在 response 阶段排除掉，代码会报错
  if (response.config.responseType === 'blob') {
    return response;
  }

  // 在router获取到route获取，这里获取到的是路由的name，不是路由的path
  // let routerName = router.app._route.name;

  // 业务上的错误
  let res = response.data;
  /* 新增：处理业务逻辑失败的情况（HTTP 200 但 success=false）
      {
          "success": false,
          "msg": "请选择是否虚拟机",
          "data": null,
          "code": 200,
          "timestamp": "2025-04-04 13:07:25"
      }
      当返回的 success 为false的时候，并且是200的时候，直接显示错误信息
  * */
  if ((res.code === 200 || res.code === 406 || res.code === 500) && res.success === false) {
    // 统一输出错误信息?
    // Message.error(res.msg); 这里会抛出异常，会出现2次错误
    // 拒绝 Promise 链
    return Promise.reject(new Error(res.msg));
  }

  if (res.code === 401){
    // 增加这一层的判断，这样就不会有多次提示了
    if (!loginErr){
      loginErr = true;
      Message.error("未登录或登录已过期");
      // 跳转到首页
      router.push({ path: "/" }).catch(err => {
        console.error('路由跳转失败:', err);
      });
    }

    // 如果所有请求都已完成并且没有活动请求，则重置 loginErr
    if (activeRequests === 0) {
      loginErr = false;
    }

  } else if (res.code === 503){
    Message.error("请求过于频繁或重复提交");
  } else if (res.code === 412){
    Message.error("无访问权限或未授权");
    router.push({ path: "/403" }).catch(err => {
      console.error('路由跳转失败:', err);
    });
  } else if (res.code === 408){
    Message.error("请求超时");
  } else if (res.code === 402){
    Message.error("业务错误，拒绝执行");
  } else if (res.code === 403){
    Message.error("非法访问");
  }

  return Promise.resolve(response)

}, error => {
  // 请求完成后减少正在进行的请求数量
  activeRequests --;

  /// 异常情况
  if (error && error.response) {
    switch (error.response.status) {
      case 400:
        error.message = '错误请求'
        break;
      case 401:
        /* 当返回的code为
        {
            "success": false,
            "msg": "令牌已过期，请重新登录",
            "data": null,
            "code": 401,
            "timestamp": "2025-04-04 12:48:14"
        }
        的时候，触发当前的操作
        * */
        error.message = '未授权，请重新登录'
        if (!loginErr) {
          loginErr = true;
          Message.error(error.message);
          router.push({ path: "/" });
        }
        if (activeRequests === 0) {
          loginErr = false;
        }
        break;
      case 403:
        error.message = '拒绝访问'
        router.push({path: "/403"})
        break;
      case 404:
        error.message = '请求错误,未找到该资源'
        // window.location.href = "/404"
        router.push({path: "/404"})
        break;
      case 405:
        error.message = '请求方法未允许'
        break;
      case 408:
        error.message = '请求超时'
        break;
      case 500:
        error.message = '服务器端出错'
        router.push({path: "/500"})
        break;
      case 501:
        error.message = '网络未实现'
        break;
      case 502:
        error.message = '网络错误'
        break;
      case 503:
        error.message = '服务不可用'
        break;
      case 504:
        error.message = '网络超时'
        break;
      case 505:
        error.message = 'http版本不支持该请求'
        break;
      default:
        error.message = `连接错误${error.response.status}`
    }
  } else {
    // 超时处理
    if (JSON.stringify(error).includes('timeout')) {
      Message.error('服务器响应超时，请刷新当前页')
    }
    error.message = '连接服务器失败'
  }

  Message.error(error.message)
  return Promise.resolve(error.response)
})

//4、--- 导出文件
export default service
